package com.example.demo.services;


import com.example.demo.identity.Group;
import com.example.demo.identity.GroupMsg;
import com.example.demo.utils.MsgType;
import com.example.demo.identity.PullGroupInfo;
import com.example.demo.repository.GroupMsgRepository;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.Updates;
import com.mongodb.client.result.UpdateResult;
import io.minio.MinioClient;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.*;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class MongoService {

    private static final Logger logger = LoggerFactory.getLogger(MongoService.class);

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private GroupMsgRepository groupMsgRepository;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private MinioClient minioClient;

    //    默认添加群成员方式
    public void addDocument(String groupId, String membersInfoList, Group group) {
        try {
            //        反序列化为PullGroupInfo对象

            List<PullGroupInfo.MembersInfo> list = objectMapper.readValue(membersInfoList,
                    objectMapper.getTypeFactory().constructCollectionType(List.class, PullGroupInfo.MembersInfo.class));
//            创建PullGroupInfo对象
            PullGroupInfo pullGroupInfo = PullGroupInfo.builder()
                    .group_id(groupId).group_name(group.getGroup_name()).group_type(group.getGroup_type()).group_key(UUID.randomUUID().toString().substring(0, 10))
                    .group_leader(group.getGroup_leader()).group_members(list).groupAvatar(group.getGroup_avatar()).build();

//            保存到MongoDB
            mongoTemplate.save(pullGroupInfo, "GroupMembersInfos");
            // 打印成功信息
            logger.info("Document added successfully with groupId: {}", groupId);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    //    通过userId获取该用户所在的所有群组Id
    public List<Object> getGroupIdsByUserId(String userId) {
//        构造查询条件        检查GroupMembersInfos.groupMembers字段是否存在
        MatchOperation matchOperation = Aggregation.match(Criteria.where("group_members").exists(true));
//        展开GroupMembersInfos.groupMembers数组
        UnwindOperation unwindOperation = Aggregation.unwind("$group_members");
//        定义聚合查询
        Aggregation aggregation = Aggregation.newAggregation(matchOperation, unwindOperation);
//        执行聚合查询
        AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, "GroupMembersInfos", Map.class);

//        获取结果
        List<Map> groupMembersList = results.getMappedResults();

//        定义一个列表来保存匹配的对象信息
        List<Object> matchedIdList = new ArrayList<>();

//        循环遍历结果列表
        for (Map map : groupMembersList) {
            Object groupMemberObject = map.get("group_members");     // 提取对象群成员对象信息
            if (groupMemberObject instanceof Map<?, ?>) {
                String currentUserId = (String) ((Map<?, ?>) groupMemberObject).get("key"); // 提取当前循环的用户Id
                if (Objects.equals(userId, currentUserId)) {
//                    匹配成功获取当前群Id
                    String groupId = (String) map.get("group_id");
                    matchedIdList.add(groupId);
                }
            }
        }
        return matchedIdList;
    }

    //    通过userId获取所在群聊信息      在这里使用了两次匹配操作，第一次：初步筛选文档，确保至少有一个groupo_members数组元素包含userId，第二次匹配就是为了每个展开的文档都能匹配userId
    public List<String> getMembersInGroup(String userId) {
        // 定义聚合查询（聚合管道）
        // $match 阶段用于过滤出 group_members 数组中包含指定 userId 的文档
        MatchOperation matchOperation = Aggregation.match(Criteria.where("group_members.key").is(userId));
        // $unwind 阶段用于将 group_members 数组中的每个元素展开成单独的文档
        UnwindOperation unwindOperation = Aggregation.unwind("group_members");
        // $match 阶段再次用于过滤出展开后的文档中包含指定 userId 的文档
        MatchOperation matchUnwindOperation = Aggregation.match(Criteria.where("group_members.key").is(userId));
        // $project 阶段用于指定返回的字段，andExclude 排除 _id 字段，并将 group_members 字段重命名为 members
        ProjectionOperation projectionOperation = Aggregation.project("group_id", "group_key", "group_leader", "group_name", "group_type", "groupAvatar")
                .andExclude("_id");
        Aggregation aggregation = Aggregation.newAggregation(matchOperation, unwindOperation, matchUnwindOperation, projectionOperation);

//        执行聚合查询
        AggregationResults<Document> results = mongoTemplate.aggregate(aggregation, "GroupMembersInfos", Document.class);
//        获取查询结果
//        List<Document> groupMembersList = results.getMappedResults();
//        获取查询结果，在获取时直接将Document对象进行toJson转换，方便后期的使用
        return results.getMappedResults().stream().map(Document::toJson).toList();
    }

    /***
     *
     * @param groupId   群Id     这是唯一的，不重复
     * @return 返回群成员消息列表
     */
    //    通过groupId获取群成员信息（包含了群聊信息，不只是获得群成员信息）      这个不用了，用了聚合函数查询
    public Optional<PullGroupInfo> getGroupMembersInfoByGroupId(String groupId) {
        Query query = new Query(Criteria.where("group_id").is(groupId));
        PullGroupInfo pullGroupInfo = mongoTemplate.findOne(query, PullGroupInfo.class, "GroupMembersInfos");
        System.out.println(pullGroupInfo);
        return Optional.ofNullable(pullGroupInfo);
    }

    //    通过groupId只获取群成员信息
    public List<PullGroupInfo.MembersInfo> getGroupMembersOnly(String groupId) {
//        1、匹配group_id
        Query query = new Query(Criteria.where("group_id").is(groupId));
//        2、投影手段
        query.fields().include("group_members");
//        3、查询一条文档
        PullGroupInfo doc = mongoTemplate.findOne(query, PullGroupInfo.class, "GroupMembersInfos");
//        4、取出成员列表并返回
        if (doc == null || doc.getGroup_members() == null) {
//            文档不存在或字段本身为空
            return Collections.emptyList();
        }
        return doc.getGroup_members();
    }


    /**
     * @param payload  用户发送的消息
     * @param senderId 发送者Id
     */
    //    将群聊消息落库   这里不需要使用ObjctMapper了，因为payload是一个Map
    public void saveGroupMsg(Map<String, Object> payload, String senderId) {
        System.out.println(payload);
        try {
            String groupId = (String) payload.get("toChatId");
            String content = (String) payload.get("content");
            String userNickName = (String) payload.get("userNickName");
            String userNickAvatar = (String) payload.get("userNickAvatar");
//        获取at列表 并解析
            List<String> atList = Optional.ofNullable(payload.get("atList"))
                    .filter(List.class::isInstance)
                    .map(object -> ((List<?>) object).stream()
                            .map(String::valueOf)
                            .filter(s -> !s.isBlank())
                            .toList())
                    .filter(list -> !list.isEmpty())
                    .orElse(null);
            //            构造实体
            GroupMsg entity = GroupMsg.builder()
//                    .id(UUID.randomUUID().toString())
                    .groupId(groupId)
                    .messageKey(UUID.randomUUID().toString().substring(0, 14))
                    .senderId(senderId)
                    .message(content)
                    .userNickName(userNickName)
                    .userNickAvatar(userNickAvatar)
                    .type(MsgType.TEXT)
                    .timeStamp(Instant.now())
                    .at(atList)   // 不写即可
                    .build();
//            落库
            groupMsgRepository.save(entity);
            logger.info(">>> connected db={}, collection={}",
                    mongoTemplate.getDb().getName(),
                    mongoTemplate.getCollectionName(GroupMsg.class));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //    获取群聊消息（groupId）
    public List<GroupMsg> getGroupMsg(String groupId) {
        System.out.println(groupId);
        Query query = new Query(Criteria.where("groupId").is(groupId));
        query.with(Sort.by(Sort.Direction.DESC, "timeStamp"));   // 按时间排序

//        排除字段
        query.fields().exclude("_id");

//        执行查询
        return mongoTemplate.find(query, GroupMsg.class, "group_msg");
    }

    //    成员退出群聊时的操作
    public void exitGroup(String groupId, String memberId) {
//        构造查询条件
        Query query = new Query(Criteria.where("group_id").is(groupId));
//        构造更新操作
        Update update = new Update().pull("group_members", new Document("key", memberId));
//        执行更新操作        第三个参数是MongoDB中的目标Collections名称
        mongoTemplate.updateFirst(query, update, "GroupMembersInfos");

        // 检查更新是否成功
        if (mongoTemplate.exists(query, "GroupMembersInfos")) {
            System.out.println("Member " + memberId + " has been removed from group " + groupId);
        } else {
            System.out.println("Group " + groupId + " not found or member " + memberId + " not removed.");
        }
    }


}
